return {
    "hrsh7th/nvim-cmp",
    event = "InsertEnter",
    dependencies = {
        "hrsh7th/cmp-nvim-lsp",
        "hrsh7th/cmp-buffer",
        "hrsh7th/cmp-path",
        "hrsh7th/cmp-cmdline",
        --- vsnip
        "hrsh7th/cmp-vsnip",
        "hrsh7th/vim-vsnip",
        "rafamadriz/friendly-snippets",
        "onsails/lspkind-nvim",
        
    },
    -- 原文档用的是vim-plug
    config = function()
        local cmp_status_ok, cmp = pcall(require, "cmp")
        if not cmp_status_ok then
          return
        end
        
        local lspkind = require('lspkind')
        
        local snip_status_ok, luasnip = pcall(require, "luasnip")
        if not snip_status_ok then
          return
        end
        
        require("luasnip.loaders.from_vscode").lazy_load()
        
        -- 下面会用到这个函数
        local check_backspace = function()
          local col = vim.fn.col "." - 1
          return col == 0 or vim.fn.getline("."):sub(col, col):match "%s"
        end
        
        
        cmp.setup({
          snippet = {
            expand = function(args)
              require('luasnip').lsp_expand(args.body)
            end,
          },
          mapping = cmp.mapping.preset.insert({
            ['<C-A-b>'] = cmp.mapping.scroll_docs(-4),
            ['<C-A-f>'] = cmp.mapping.scroll_docs(4),
            ['<C-e>'] = cmp.mapping.abort(),  -- 取消补全，esc也可以退出
            ['<A-S-e>'] = cmp.mapping.confirm({ select = true }),
        
            ["<Tab>"] = cmp.mapping(function(fallback)
              if cmp.visible() then
                cmp.select_next_item()
              elseif luasnip.expandable() then
                luasnip.expand()
              elseif luasnip.expand_or_jumpable() then
                luasnip.expand_or_jump()
              elseif check_backspace() then
                fallback()
              else
                fallback()
              end
            end, {
              "i",
              "s",
            }),
        
            ["<S-Tab>"] = cmp.mapping(function(fallback)
              if cmp.visible() then
                cmp.select_prev_item()
              elseif luasnip.jumpable(-1) then
                luasnip.jump(-1)
              else
                fallback()
              end
            end, {
              "i",
              "s",
            }),
          }),
        
          -- 这里重要
          sources = cmp.config.sources({
            { name = 'nvim_lsp' },
            { name = 'luasnip' },
            { name = 'path' },
          }, {
            { name = 'buffer' },
          }),
        formatting = {
            format = lspkind.cmp_format({
              with_text = true, -- do not show text alongside icons
              maxwidth = 50, -- prevent the popup from showing more than provided characters (e.g 50 will not show more than 50 characters)
              before = function (entry, vim_item)
                -- Source 显示提示来源
                vim_item.menu = "["..string.upper(entry.source.name).."]"
                return vim_item
              end
            })
        }
        })
    end
}
